#!/bin/bash
############################################################################
# FUNCTION : Add whitelist symbols to the corresponding image based on the
#            product information and check the validity of the symbols when
#            building the kernel.
# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved
############################################################################
SCRIPT_DIR=$(dirname $(readlink -f $0))
KERNEL_DIR=${SCRIPT_DIR%/*}
PRODUCT_CONF="$KERNEL_DIR/rtos/trustlists/product.conf"
GENERATED_DIR="$KERNEL_DIR/rtos/trustlists/generated"
source $PRODUCT_CONF

function usage() {
	cat <<-END >&2
	USAGE: ./add_trustlist_sym.sh [-o OUTPUT] [-c LIST] [-h]
	                -o OUTPUT       # generate trustlist
	                -c LIST         # check if symbol is valid
	                -h              # this usage message
END
	exit
}

function die() {
	echo >&2 "$@"
	exit 1
}

# Check if the product includes a specific architecture according to product.conf
# ${1} - product: gx,optix,wireless_basestation,it,mbsc
# ${2} - image
function is_contained() {
	local product="${1}[@]"

	for img in ${!product}; do
		[[ "$img" == "$2" ]] && return 0
	done
	return 1
}

function add_symbol() {
	local src="${KERNEL_DIR}/rtos/trustlists/rtos-trustlist-${1}"
	cat $src >> $2
	sort -u $2 -o $2
}

function gen_trustlist() {
	local image=${1##*rtos-trustlist-}
	local rtos_trustlist=${1##*/}
	rtos_trustlist="$GENERATED_DIR/$rtos_trustlist"

	[[ -d "$GENERATED_DIR" ]] && rm -rf "$GENERATED_DIR"
	mkdir -p $GENERATED_DIR
	touch $rtos_trustlist

	for i in $g_rtos_product_list; do
		is_contained $i $image && add_symbol $i $rtos_trustlist
	done
	return 0
}

# Check if the symbol in the trustlist is a function and remove non-func
# ${1} - trustlist
function check_is_func() {
	local cur_trustlist="$1"
	local new_trustlist="$1.tmpnew"
	local function_list="$GENERATED_DIR/func"
	local system_map="$KERNEL_DIR/System.map"

	[[ -f "$system_map" ]] || die "ERROR: $system_map does not exist"
	# Check if the symbol is a function
	grep -i " [tw] " $system_map > $function_list
	# The symbols in trustlist with "and, are filtered out to match System.map
	sed -i s/[\",]//g $cur_trustlist
	for sym in $(cat $cur_trustlist); do
		if grep -wq "${sym}$" $system_map; then
			if grep -wq "${sym}$" $function_list; then
				echo $sym >> $new_trustlist
			else
				echo "RTOS Trustlist: $sym is not a function, only exporting function is allowed"
			fi
		fi
	done
	[[ -f "$function_list" ]] && rm -f "$function_list"
	[[ -f "$new_trustlist" ]] && mv -f "$new_trustlist" "$cur_trustlist"
	return 0
}

# Check if the symbol in the trustlist is exported
# ${1} - trustlist
function check_is_exported() {
	local exported_sym="$KERNEL_DIR/Module.symvers"

	[[ -f "$exported_sym" ]] || die "ERROR: $exported_sym does not exist"

	for sym in $(cat $1); do
		if (grep -wq $sym $exported_sym); then
			echo "RTOS Trustlist: $sym is exported by EXPORT_*, please remove it"
		fi
	done
	return 0
}

function check_symbol_valid() {
	local rtos_trustlist=${1##*/}
	rtos_trustlist="$GENERATED_DIR/$rtos_trustlist"

	check_is_func $rtos_trustlist
	check_is_exported $rtos_trustlist
	return 0
}

while getopts o:c:h opt
do
	case "$opt" in
	o)	gen_trustlist $OPTARG ;;
	c)	check_symbol_valid $OPTARG ;;
	h|?)	usage ;;
	esac
done
